
#include "PreHeader.h"
#include "cMsgManager.h"

cMsgManager* cMsgManager::it()
{
	static cMsgManager msgManager;
	return &msgManager;
}

cMsgManager::cMsgManager()
{
}

cMsgManager::~cMsgManager()
{
	for (tPostMsgList::iterator i_msg = m_postMsgList.begin(); i_msg != m_postMsgList.end(); ++i_msg)
	{
		delete i_msg->msg;
	}
}

tBool cMsgManager::SendMsg(sMsg& msg)
{
	if (msg.msgTargetID == MSG_TARGET_ID_ALL)
	{
		foreach (tTargetMap::value_type& value, m_targetMap)
		{
			iMsgTargetBase* target = value.second;
			target->_ON_MSG(msg);
		}

		return true;
	}

	iMsgTargetBase* target = FindTarget(msg.msgTargetID);

	if (target == NULL)
	{
		return false;
	}

	return target->_ON_MSG(msg);
}

tBool cMsgManager::SendMsg(tMsgTargetID targetID, sMsg& msg)
{
	msg.msgTargetID = targetID;
	return SendMsg(msg);
}

tBool cMsgManager::PostMsg(sMsg& msg, tFloat time)
{
	if (msg.msgTargetID != MSG_TARGET_ID_ALL)
	{
		iMsgTargetBase* target = FindTarget(msg.msgTargetID);
		if (target == NULL)
		{
			return false;
		}
	}

	sPostMsgInfo info;
	info.msg = msg.Copy();
	info.time = time;
	m_postMsgList.push_back(info);
	return true;
}

tSize cMsgManager::CancelPostMsgTo(tMsgTargetID targetID)
{
	tSize count = 0;
	for (tPostMsgList::iterator i_msg = m_postMsgList.begin(); i_msg != m_postMsgList.end(); ++i_msg)
	{
		if (i_msg->msg->msgTargetID == targetID)
		{
			count++;
		}
	}
	if (count > 0)
	{
		m_cancelMsgTargetIDSet.insert(targetID);
	}

	return count;
}

tBool cMsgManager::PostMsg(tMsgTargetID targetID, sMsg& msg, tFloat time)
{
	msg.msgTargetID = targetID;
	return PostMsg(msg, time);
}

void cMsgManager::Update(tFloat dt)
{
	tPostMsgUpdateInfoArray updateInfoArray;
	updateInfoArray.reserve(m_postMsgList.size());

	for (tPostMsgList::iterator i_msg = m_postMsgList.begin(); i_msg != m_postMsgList.end(); ++i_msg)
	{
		sPostMsgUpdateInfo updateInfo;
		updateInfo.i_target = i_msg;
		updateInfo.target = &(*i_msg);
		updateInfoArray.push_back(updateInfo);
	}

	foreach (sPostMsgUpdateInfo& updateInfo, updateInfoArray)
	{
		if (m_cancelMsgTargetIDSet.size() > 0)
		{
			if (m_cancelMsgTargetIDSet.find(updateInfo.target->msg->msgTargetID) != m_cancelMsgTargetIDSet.end())
			{
				SAFE_DELETE(updateInfo.target->msg);
				m_postMsgList.erase(updateInfo.i_target);
				continue;
			}
		}

		updateInfo.target->time -= dt;
		if (updateInfo.target->time <= 0.f)
		{
			SendMsg(*updateInfo.target->msg);
			SAFE_DELETE(updateInfo.target->msg);
			m_postMsgList.erase(updateInfo.i_target);
		}
	}
	m_cancelMsgTargetIDSet.clear();
}

tBool cMsgManager::RegisterTarget(iMsgTargetBase* target)
{
	if (target == NULL)
	{
		return false;
	}

	tTargetMap::iterator iter = m_targetMap.find(target->GetMsgTargetID());
	if (iter != m_targetMap.end())
	{
		return false;
	}

	m_targetMap.insert(std::make_pair(target->GetMsgTargetID(), target));
	return true;
}

tBool cMsgManager::UnregisterTarget(iMsgTargetBase* target)
{
	if (target == NULL)
	{
		return false;
	}

	return m_targetMap.erase(target->GetMsgTargetID()) > 0 ? true : false;
}

iMsgTargetBase* cMsgManager::FindTarget(tMsgTargetID id)
{
	tTargetMap::iterator iter = m_targetMap.find(id);
	if (iter == m_targetMap.end())
	{
		return NULL;
	}
	return iter->second;
}
